// -----------------------------
// Author: 		Dhaenens Gert	
// Creation: 	2/21/2015 7:40:03 PM				
// -----------------------------

#include "CThread.h"

namespace Flow
{

	CThread::CThread()
		: m_hThread(NULL)
		, m_Function(nullptr)
		, m_lpArgs(nullptr)
	{
	}

	CThread::~CThread()
	{
	}

	void CThread::Release()
	{
		delete this;
	}

	void CThread::Start(ThreadProc fn, void* lpArgs)
	{
		ASSERT(!IsRunning());
		if (IsRunning())
			return;

		m_Function = fn;
		m_lpArgs = lpArgs;

		m_hThread = CreateThread(NULL, 0, CThread::ThreadProcWrapper, this, 0, nullptr);
		ASSERT(m_hThread != INVALID_HANDLE_VALUE);
	}
	void CThread::Stop()
	{
		ASSERT(IsRunning());
		if (!IsRunning())
			return;
	}

	void CThread::WaitForExit()
	{
		ASSERT(IsRunning());
		if (!IsRunning())
			return;

		DWORD dwWaitResult = WaitForSingleObject(m_hThread, INFINITE);
		ASSERT(dwWaitResult == WAIT_OBJECT_0);
	}

	Bool CThread::IsRunning() const
	{
		DWORD dwWaitResult = WaitForSingleObject(m_hThread, 0);
		if (dwWaitResult == WAIT_TIMEOUT)
			return true;
		return false;
	}

	DWORD WINAPI CThread::ThreadProcWrapper(void* lpArgs)
	{
		CThread* lpThread = reinterpret_cast<CThread*>(lpArgs);
		ASSERT(lpThread);

		ThreadProc lpThreadFn = lpThread->m_Function;
		void* lpThreadArgs = lpThread->m_lpArgs;

		ASSERT(lpThreadFn);

		lpThreadFn(lpThreadArgs);

		return 0;
	}

}